package com.winphone.uvam.service.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.winphone.uvam.common.Constant;
import com.winphone.uvam.entity.FileInfo;
import com.winphone.uvam.mapper.FileInfoMapper;
import com.winphone.uvam.service.IFileInfoService;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import java.io.*;
import java.util.Date;

/**
 * <p>
 * 文件表 服务实现类
 * </p>
 *
 * @author LiaoJunJie
 * @since 2017-12-18
 */
@Service
public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements IFileInfoService {

    private static Logger logger = LoggerFactory.getLogger(FileInfoServiceImpl.class);


    @Autowired
    private FileInfoMapper fileInfoMapper;

    @Override
    public FileInfo getById(Long id) {
        return fileInfoMapper.selectById(id);
    }

    @Override
    public FileInfo getByMd5(String md5) {
        return fileInfoMapper.getByMd5(md5);
    }

    @Override
    public void writeFile(String md5, OutputStream out, String fileSavePath, long skip) throws IOException {
        try (InputStream inputStream = readFile(md5, fileSavePath)) {
            if (skip > 0) {
                inputStream.skip(skip);
            }
            StreamUtils.copy(inputStream, out);
        }
    }

    /**
     * 将服务器中的file转成inputStream
     *
     * @param fileId 文件id
     * @return
     * @throws FileNotFoundException
     */
    public InputStream readFile(Long fileId, String fileSavePath) throws FileNotFoundException {
        FileInfo fileEntity = fileInfoMapper.selectById(fileId);
        //配置中的文件上传根路径
        String filePath = fileSavePath + "/" + fileEntity.getLocation();
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException("file not found");
        }
        try {
            return new FileInputStream(file);
        } catch (FileNotFoundException ignore) {
            //  never happen
            throw new FileNotFoundException("file not found");
        }
    }

    /**
     * 将服务器中的file转成inputStream
     *
     * @param md5 文件id
     * @return
     * @throws FileNotFoundException
     */
    public InputStream readFile(String md5, String fileSavePath) throws FileNotFoundException {
        FileInputStream fileInputStream = null;
        FileInfo fileEntity = fileInfoMapper.getByMd5(md5);
        //配置中的文件上传根路径
        String filePath = fileSavePath + "/" + fileEntity.getLocation()+".mp4";
        File file = new File(filePath);
        if (!file.exists()) {
            logger.error("file not found");
        }
        try {
            fileInputStream = new FileInputStream(file);
        } catch (FileNotFoundException ignore) {
            logger.error("file not found");
        }
        return fileInputStream;
    }

    /**
     * 保存文件
     *  @param fileStream
     * @param fileSavePath 文件保存路径
     * @param fileName     文件名
     * @param contentType
     * @param creator      @return
     */
    @Override
    public FileInfo saveFile(InputStream fileStream, String fileSavePath, String fileName,String prefix, String contentType, String creator) {
        FileInfo fileInfo = new FileInfo();
        //文件上传临时路径
        String fileTempPath = fileSavePath.concat("/").concat("temp");

        File path = new File(fileTempPath);
        if (!path.exists()) {
            path.mkdirs(); //创建目录
        }
        String newName = String.valueOf(System.nanoTime()); //临时文件名 ,纳秒的md5值

        //创建新文件名
        String fileAbsName = fileTempPath.concat("/").concat(newName).concat("."+prefix);

        long fileLength = 0L;
        try (BufferedInputStream in = new BufferedInputStream(fileStream);
             FileOutputStream os = new FileOutputStream(fileAbsName)) {
            fileLength = StreamUtils.copy(in, os);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        File newFile = new File(fileAbsName);
        //获取文件的md5值
        String md5 = null;
        try (FileInputStream inputStream = new FileInputStream(newFile)) {
            md5 = DigestUtils.md5Hex(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //  判断文件是否已经存在
        FileInfo fileEntity_db = fileInfoMapper.getByMd5(md5);
        if (fileEntity_db != null) {
            File file = new File(fileSavePath + "/" + fileEntity_db.getLocation());
            if (file.exists()) {
                newFile.delete();//文件已存在则删除临时文件不做处理
            } else {
                //将临时文件保存到正式文件路径,修改文件名为MD5
                newFile.renameTo(new File(fileSavePath.concat("/").concat(md5).concat("."+prefix)));
            }
            return fileEntity_db;
        } else {
            //修改临时文件名称并保存到临时路径下，用md5作为文件名称
            newFile.renameTo(new File(fileSavePath.concat("/").concat(md5).concat("."+prefix)));
        }

        //封装实体
        fileInfo.setMd5(md5);
        fileInfo.setSize(fileLength);
        fileInfo.setType(contentType);
        fileInfo.setName(fileName);
        fileInfo.setLocation(md5);
        fileInfo.setCreateBy(Long.parseLong(creator));
        fileInfo.setCreateDate(new Date());
        fileInfo.setIsDelete(Constant.DELETE_NO);

        //保存db
        if (!insertOrUpdate(fileInfo)) {
            //TODO 修改为自定义异常
            throw new RuntimeException("file上传失败");
        }
        return fileInfo;
    }
}
